package xyz.thoughtset.viewer.modules.ds.core.factory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import xyz.thoughtset.viewer.common.connector.linker.ConnBuilder;
import xyz.thoughtset.viewer.common.connector.linker.LinkerHelper;
import xyz.thoughtset.viewer.modules.ds.core.dao.DsConfigDao;
import xyz.thoughtset.viewer.modules.ds.core.entity.DsConfig;
import xyz.thoughtset.viewer.modules.ds.core.entity.LinkerConfig;
import xyz.thoughtset.viewer.modules.ds.core.service.LinkerConfigService;

import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class ConnectFactory implements InitializingBean, DisposableBean {
    @Autowired
    private ObjectMapper mapper;
    @Autowired
    private LinkerConfigService linkerConfigService;
    @Autowired
    private DsConfigDao dsConfigDao;
    private ConcurrentHashMap<String, Object> DS_CACHE = new ConcurrentHashMap<>();
    public static final DsConfig BLOCK_DS_CONFIG = new DsConfig();

    public <T> T buildConnect(String dsId,Class<T> targetType) {
        return (T) buildConnect(dsId);
    }

    public Object buildConnect(String dsId) {
        Object result = DS_CACHE.get(dsId);
        if (result!=null) return result;
        DsConfig dsc = dsConfigDao.selectDetail(dsId);
        Properties properties = null;
        String settingsStr = dsc.getOtherSettings();
        if(StringUtils.hasText(settingsStr)){
            LinkedHashMap<String,String> settings = null;
            try {
                settings = mapper.readValue(settingsStr, LinkedHashMap.class);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            if (settings!=null){
                properties = new Properties();
                properties.putAll(settings);
            }
        }
        ConnBuilder connBuilder = findConnBuilder(dsc);
        result = connBuilder.buildConnect(dsc,properties);
        DS_CACHE.put(dsId,result);
        return result;
    }

    public ConnBuilder findConnBuilder(DsConfig ds){
        ConnBuilder connBuilder = LinkerHelper.getConnBuilder(ds);
        if (Objects.nonNull(connBuilder)){
            return connBuilder;
        }
        LinkerConfig config = linkerConfigService.getById(ds.getLinkerType());
        connBuilder = LinkerHelper.createConnBuilder(config.buildLinker());
        return connBuilder;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("ConnectFactory initialized, DS_CACHE size: {}", DS_CACHE.size());
//        DS_CACHE.put(BLOCK_DS_CONFIG.getId(), BLOCK_DS_CONFIG);
    }

    @Override
    public void destroy() throws Exception {
        log.info("Destroying ConnectFactory, clearing DS_CACHE");
        DS_CACHE.clear();
    }
}
